# -*- coding: utf-8 -*-

"""
Module for Common Functions.
"""
from PyQt5.QtCore import QThread, pyqtSignal, Qt
import requests
import os
from MakeSDCardProxy import MakeSDCardProxy
import time
import subprocess
import logging
import collections
import sys
import configparser
import paramiko
import pickle
import base64
import DialogResult
from PyQt5.QtWidgets import *

breakpoint_flag = 1



class Log(object):
    '''
封装后的logging
    '''

    def __init__(self, log_name="xxxx.log", logger=None, log_cate='search'):
        '''
            指定保存日志的文件路径，日志级别，以及调用文件
            将日志存入到指定的文件中
        '''

        # 创建一个logger
        self.logger = logging.getLogger(logger)
        self.logger.setLevel(logging.DEBUG)
        # 创建一个handler，用于写入日志文件
        self.log_time = time.strftime("%Y_%m_%d")
        # file_dir = os.getcwd() + '/../log'
        # if not os.path.exists(file_dir):
        #     os.mkdir(file_dir)
        # self.log_path = file_dir
        self.log_name = log_name
        # print(self.log_name)

        # fh = logging.FileHandler(self.log_name, 'a')  # 追加模式  这个是python2的
        fh = logging.FileHandler(self.log_name, 'a', encoding='utf-8')  # 这个是python3的
        fh.setLevel(logging.INFO)

        # 再创建一个handler，用于输出到控制台
        ch = logging.StreamHandler()
        ch.setLevel(logging.ERROR)

        # 定义handler的输出格式
        formatter = logging.Formatter(
            '[%(asctime)s] %(filename)s->%(funcName)s line:%(lineno)d [%(levelname)s]%(message)s')
        fh.setFormatter(formatter)
        ch.setFormatter(formatter)

        # 给logger添加handler
        self.logger.addHandler(fh)
        self.logger.addHandler(ch)

        #  添加下面一句，在记录日志之后移除句柄
        # self.logger.removeHandler(ch)
        # self.logger.removeHandler(fh)
        # 关闭打开的文件
        fh.close()
        ch.close()

    def getlog(self):
        return self.logger


requests.packages.urllib3.disable_warnings()


class DownloadThread(QThread):
    download_progress_signal = pyqtSignal(int, str)
    download_finished_signal = pyqtSignal(int, str)

    def __init__(self, download_url, file_path, key, checkBox_tar_update_source=None, checkBox_iso_source=None, buffer=10240, project_dir=None):
        super(DownloadThread, self).__init__()
        self.key = key
        self.tar_download = checkBox_tar_update_source
        self.iso_download = checkBox_iso_source
        self.download_url = download_url
        # self.file_size = file_size
        # self.file_obj = file_obj
        self.buffer = buffer
        # self.headers = headers
        self.file_path = file_path
        self.stop_flag = False
        self.project_dir = project_dir

    def run(self):
        try:
            global breakpoint_flag
            breakpoint_flag = breakpoint_flag + 1
            tar_download = self.tar_download.currentText()
            if self.iso_download is not None:
                iso_download = self.iso_download.currentText()
            conf = configparser.ConfigParser()
            conf.read(self.project_dir + "/config.ini")
            key_info = ""
            if self.key == "run_package":
                if tar_download == "1.31.T20.B200":
                    self.download_url = conf.get("mini_developerkit_version_info2", "url")
                elif tar_download == "1.31.0.B080":
                    self.download_url = conf.get("mini_developerkit_version_info", "url")
            elif self.key == "ddk":
                if tar_download == "1.31.T20.B200":
                    self.download_url = conf.get("ddk_version_info2", "url")
                elif tar_download == "1.31.0.B080":
                    self.download_url = conf.get("ddk_version_info", "url")
            elif self.key == "ubuntu_arm":
                if iso_download == "use official image: ubuntu-16.04.4-server-arm64.iso":
                    self.download_url = conf.get("iso_version_info1", "url")
                    key_info = conf.get("iso_version_info1", "name")
                if iso_download == "use official image: ubuntu-16.04.5-server-arm64.iso":
                    self.download_url = conf.get("iso_version_info2", "url")
                    key_info = conf.get("iso_version_info2", "name")
                if iso_download == "use official image: ubuntu-16.04.6-server-arm64.iso":
                    self.download_url = conf.get("iso_version_info3", "url")
                    key_info = conf.get("iso_version_info3", "name")
                if iso_download == "use repo.huaweicloud.com image: ubuntu-16.04.4-server-arm64.iso":
                    self.download_url = conf.get("iso_version_info4", "url")
                    key_info = conf.get("iso_version_info4", "name")
                if iso_download == "use repo.huaweicloud.com image: ubuntu-16.04.5-server-arm64.iso":
                    self.download_url = conf.get("iso_version_info5", "url")
                    key_info = conf.get("iso_version_info5", "name")
                if iso_download == "use repo.huaweicloud.com image: ubuntu-16.04.6-server-arm64.iso":
                    self.download_url = conf.get("iso_version_info6", "url")
                    key_info = conf.get("iso_version_info6", "name")

            file_path_dir = self.file_path
            self.file_path = os.path.join(self.file_path, os.path.basename(self.download_url))
            # get total size
            total_size = int(requests.get(self.download_url, stream=True).headers.get('Content-Length'))

            if ADKUtils.is_file_path_exists(self.file_path):
                res = ADKUtils.is_file_size_ok(self.file_path, total_size)
                if res == 1:
                    if self.key == "ubuntu_arm" and key_info == "ubuntu-16.04.4-server-arm64.iso":
                        md_5 = ADKUtils.md5sum_func(self.file_path)
                        if md_5 == "f5d4b81bc423c003f48e6160831d3446":
                            self.download_finished_signal.emit(1, self.key)
                        else:
                            ADKUtils.show_message("package md5 check error, please delete it manually, and retry")
                            self.download_finished_signal.emit(2, self.key)
                    elif self.key == "ubuntu_arm" and key_info == "ubuntu-16.04.5-server-arm64.iso":
                        md_5 = ADKUtils.md5sum_func(self.file_path)
                        if md_5 == "617d3e809204e909af1cc7f567494e47":
                            self.download_finished_signal.emit(1, self.key)
                        else:
                            ADKUtils.show_message("package md5 check error, please delete it manually, and retry")
                            self.download_finished_signal.emit(2, self.key)
                    elif self.key == "ubuntu_arm" and key_info == "ubuntu-16.04.6-server-arm64.iso":
                        md_5 = ADKUtils.md5sum_func(self.file_path)
                        if md_5 == "98d719740eff41b1882cff2f0a789f3f":
                            self.download_finished_signal.emit(1, self.key)
                        else:
                            ADKUtils.show_message("package md5 check error, please delete it manually, and retry")
                            self.download_finished_signal.emit(2, self.key)
                    else:
                        self.download_finished_signal.emit(1, self.key)
                    return
                elif res == 2:
                    self.download_finished_signal.emit(2, self.key)
                    if ADKUtils.show_message_if_to_delete("Found the file with the same name under the path, but the file size is large than the target file, if you want to detele it, click OK."):
                        command_str = 'rm -rf ' + file_path_dir + self.key
                        (ret, output) = subprocess.getstatusoutput(command_str)
                        if not ret == 0:
                            ADKUtils.show_message("Delete error, please delete it manually.")
                    return
                else:
                    if breakpoint_flag == 3 and not ADKUtils.show_message_if_to_delete("Found the file with the same name under the path, but the file size is small than the target file, do you wan to continue?"):
                        self.download_finished_signal.emit(2, self.key)
                        return
            else :
                command_str = 'rm -rf ' + file_path_dir + '/mini_developerkit*.rar'
                (ret, output) = subprocess.getstatusoutput(command_str)
                command_str = 'rm -rf ' + file_path_dir + '/Ascend_DDK-*.tar.gz'
                (ret, output) = subprocess.getstatusoutput(command_str)

            self.download_finished_signal.emit(3, self.key)
            if os.path.exists(self.file_path):
                offset = os.path.getsize(self.file_path)
            else:
                offset = 0
            headers = {'Range': 'bytes=%d-' % offset}
            r = requests.get(self.download_url, stream=True, headers=headers)
            with open(self.file_path, "ab") as f:
                for chunk in r.iter_content(chunk_size=self.buffer):
                    if not chunk:
                        break
                    if self.stop_flag:
                        self.download_finished_signal.emit(4, self.key)
                        print("paused in download thread.")
                        return

                    offset += len(chunk)
                    f.write(chunk)
                    f.flush()

                    progress = offset / int(total_size) * 100
                    self.download_progress_signal.emit(int(progress), self.key)
                    if progress == 100:
                        if self.key == "ubuntu_arm" and key_info == "ubuntu-16.04.4-server-arm64.iso":
                            md_5 = ADKUtils.md5sum_func(self.file_path)
                            if md_5 == "f5d4b81bc423c003f48e6160831d3446":
                                self.download_finished_signal.emit(1, self.key)
                            else:
                                ADKUtils.show_message("package md5 check error, please delete it manually and retry")
                                self.download_finished_signal.emit(2, self.key)
                        elif self.key == "ubuntu_arm" and key_info == "ubuntu-16.04.5-server-arm64.iso":
                            md_5 = ADKUtils.md5sum_func(self.file_path)
                            if md_5 == "617d3e809204e909af1cc7f567494e47":
                                self.download_finished_signal.emit(1, self.key)
                            else:
                                ADKUtils.show_message("package md5 check error, please delete it manually, and retry")
                                self.download_finished_signal.emit(2, self.key)
                        elif self.key == "ubuntu_arm" and key_info == "ubuntu-16.04.6-server-arm64.iso":
                            md_5 = ADKUtils.md5sum_func(self.file_path)
                            if md_5 == "98d719740eff41b1882cff2f0a789f3f":
                                self.download_finished_signal.emit(1, self.key)
                            else:
                                ADKUtils.show_message("package md5 check error, please delete it manually, and retry")
                                self.download_finished_signal.emit(2, self.key)
                        else:
                            self.download_finished_signal.emit(1, self.key)
        except Exception as e:
            self.download_finished_signal.emit(2, self.key)
            print(e)


class AptInstallThread(QThread):

    apt_update_begin_signal = pyqtSignal(str)
    apt_update_signal = pyqtSignal(str, int)


    # tell main which package begin to install.
    apt_install_begin_signal = pyqtSignal(str)

    # tell main the pacakage install result.
    apt_install_signal = pyqtSignal(str, int)

    # tell main the package have been already installed.
    apt_already_installed = pyqtSignal(str)

    # tell main all have been down.
    apt_all_have_done = pyqtSignal()

    # insall_list in the install list will be install by apt
    def __init__(self, install_list, apt_log_path, checkBox_apt_update_source, b_sudo=False, passwd="", mylogger=None, source_dict=None):
        """
        initial the apt install thread.
        :param install_list: the list will be installed by apt-get.
        :param apt_log_path: the path to save the apt-get install log. default: /tmp/makesd/apt_log/.*.log
        :param b_apt_need_update: if need to do apt-get update. default: False.
        """
        super(AptInstallThread, self).__init__()
        self.install_list = install_list
        self.apt_log_path = apt_log_path
        #self.apt_need_update = b_apt_need_update
        self.b_sudo = b_sudo
        self.passwd = passwd
        self.apt_update_source = checkBox_apt_update_source
        self.source_flag_dict = source_dict

        self.logger = mylogger

        self.stop_flag = False
        self.apt_update_status = True
        self.apt_source_dict = collections.OrderedDict()
        self.apt_source_dict["use the http://mirrors.huaweicloud.com/ apt-get source"] = [
                "deb https://repo.huaweicloud.com/ubuntu/ xenial main restricted universe multiverse",
                "deb https://repo.huaweicloud.com/ubuntu/ xenial-updates main restricted universe multiverse",
                "deb https://repo.huaweicloud.com/ubuntu/ xenial-backports main restricted universe multiverse",
                "deb https://repo.huaweicloud.com/ubuntu/ xenial-security main restricted universe multiverse"]
        self.apt_source_dict["use the https://mirrors.tuna.tsinghua.edu.cn/ubuntu/apt-get source"] = [
                "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiverse",
                "deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiverse",
                "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse",
                "deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse",
                "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse",
                "deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse",
                "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse",
                "deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse",
                "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse",
                "deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse"]
        self.apt_source_dict["use the http://mirrors.aliyun.com/ubuntu/ apt-get source"] = [
                "deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted universe multiverse",
                "deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted universe multiverse",
                "deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted universe multiverse",
                "deb http://mirrors.aliyun.com/ubuntu/ xenial-proposed main restricted universe multiverse",
                "deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse",
                "deb-src http://mirrors.aliyun.com/ubuntu/ xenial main restricted universe multiverse",
                "deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted universe multiverse",
                "deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted universe multiverse",
                "deb-src http://mirrors.aliyun.com/ubuntu/ xenial-proposed main restricted universe multiverse",
                "deb-src http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse"]
        self.apt_source_dict["use the http://mirrors.ustc.edu.cn/ubuntu/ apt-get source"] = [
                "deb http://mirrors.ustc.edu.cn/ubuntu/ xenial main restricted universe multiverse",
                "deb http://mirrors.ustc.edu.cn/ubuntu/ xenial-security main restricted universe multiverse",
                "deb http://mirrors.ustc.edu.cn/ubuntu/ xenial-updates main restricted universe multiverse",
                "deb http://mirrors.ustc.edu.cn/ubuntu/ xenial-proposed main restricted universe multiverse",
                "deb http://mirrors.ustc.edu.cn/ubuntu/ xenial-backports main restricted universe multiverse",
                "deb-src http://mirrors.ustc.edu.cn/ubuntu/ xenial main restricted universe multiverse",
                "deb-src http://mirrors.ustc.edu.cn/ubuntu/ xenial-security main restricted universe multiverse",
                "deb-src http://mirrors.ustc.edu.cn/ubuntu/ xenial-updates main restricted universe multiverse",
                "deb-src http://mirrors.ustc.edu.cn/ubuntu/ xenial-proposed main restricted universe multiverse",
                "deb-src http://mirrors.ustc.edu.cn/ubuntu/ xenial-backports main restricted universe multiverse"]

    def run(self):
        apt_update = self.apt_update_source.currentText()
        if apt_update != "use the default apt-get source":
            if self.b_sudo ==False:
                self.logger.error("change apt-get source should in root permission")
                self.exit(0)
            flag = True
            for key in self.install_list:
                if not ADKUtils.is_apt_installed(key):
                    flag = False
                    continue
                self.apt_already_installed.emit(key)
            if flag:
                key = "update"
                self.apt_all_have_done.emit()
                self.apt_update_signal.emit(key, 2)
            else:
                if self.source_flag_dict[apt_update] == [True]:
                    key = "not_update"
                    self.apt_update_begin_signal.emit(key)
                else:
                    (ret, output) = subprocess.getstatusoutput('ps -ef | grep apt-get | grep -v "grep"')
                    if not output.find('apt-get') == -1:
                        print("Apt is running, you can not continue, please kill it in terminal.")
                        ADKUtils.show_message("Apt is running, you can not continue, please kill it in terminal.")
                        for key in self.install_list:
                            if not ADKUtils.is_apt_installed(key):
                                self.apt_install_signal.emit(key, False)
                        self.apt_update_status = False
                        self.apt_update_signal.emit("update", 3)
                        self.exit(0)

                    key = "update"
                    self.logger.info("apt-get update begin.")
                    self.apt_update_begin_signal.emit(key)
                    with open('sources.list', 'w') as f:
                        for item in self.apt_source_dict[apt_update]:
                            f.write(item+'\n')
                    command_str = 'echo ' + self.passwd + ' | sudo -S cp /etc/apt/sources.list /etc/apt/sources.list.old'
                    (ret, output) = subprocess.getstatusoutput(command_str)
                    if 1 == ret:
                        self.logger.info("apt-get update failed in copy /etc/apt/sources.list to sources.list.old." )
                        return

                    command_str = 'echo ' + self.passwd + ' | sudo -S cp sources.list /etc/apt/sources.list'
                    (ret, output) = subprocess.getstatusoutput(command_str)
                    if 1 == ret:
                        self.logger.info("apt-get update failed in copy sources.list to /etc/apt/sources.list." )
                        return
                    if self.b_sudo:
                        command_str = 'echo ' + self.passwd + ' | sudo -S apt-get update -y >> ' + self.apt_log_path
                        command_str_x = 'echo ' + '***' + ' | sudo -S apt-get update -y >> ' + self.apt_log_path

                    else:
                        command_str = 'apt-get update -y >> ' + self.apt_log_path
                        command_str_x = 'apt-get update -y >> ' + self.apt_log_path

                    self.logger.info(command_str_x)
                    (ret, output) = subprocess.getstatusoutput(command_str)

                    command_str_cp = 'echo ' + self.passwd + ' | sudo -S cp /etc/apt/sources.list.old /etc/apt/sources.list'
                    (ret_cp, output_cp) = subprocess.getstatusoutput(command_str_cp)

                    if 1 == ret_cp:
                        self.logger.info("apt-get update failed in copy /etc/apt/sources.list.old to /etc/apt/sources.list." )

                    if 0 == ret:
                        self.logger.info("apt-get %s successfully." % key)
                        self.apt_update_signal.emit(key, 1)
                    else:
                        self.logger.info("apt-get %s failed, maybe you should change sources and retry" % key)
                        self.apt_update_status = False
                        self.apt_update_signal.emit(key, 3)
                        self.exit(0)
        else:
            flag = True
            for key in self.install_list:
                if not ADKUtils.is_apt_installed(key):
                    flag = False
                    continue
                self.apt_already_installed.emit(key)

            if flag:
                key = "update"
                self.apt_update_signal.emit(key, 2)
                self.apt_all_have_done.emit()
            else:
                if self.source_flag_dict[apt_update] == [True]:
                    key = "not_update"
                    self.apt_update_begin_signal.emit(key)
                else:
                    (ret, output) = subprocess.getstatusoutput('ps -ef | grep apt-get | grep -v "grep"')
                    if not output.find('apt-get') == -1:
                        flag = True
                        print("Apt is running, you can not continue, please kill it in terminal.")
                        ADKUtils.show_message("Apt is running, you can not continue, please kill it in terminal.")
                        for key in self.install_list:
                            if not ADKUtils.is_apt_installed(key):
                                self.apt_install_signal.emit(key, False)
                        self.apt_update_status = False
                        self.apt_update_signal.emit("update", 3)
                        self.exit(0)
                    else:
                        key = "update"
                        self.logger.info("apt-get update begin.")
                        self.apt_update_begin_signal.emit(key)

                        if self.b_sudo:
                            command_str = 'echo ' + self.passwd + ' | sudo -S apt-get update -y >> ' + self.apt_log_path
                            command_str_x = 'echo ' + '***' + ' | sudo -S apt-get update -y >> ' + self.apt_log_path

                        else:
                            command_str = 'apt-get update -y >> ' + self.apt_log_path
                            command_str_x = 'apt-get update -y >> ' + self.apt_log_path

                        self.logger.info(command_str_x)
                        (ret, output) = subprocess.getstatusoutput(command_str)

                        if 0 == ret:
                            self.logger.info("apt-get %s successfully." % key)
                            self.apt_update_signal.emit(key, 1)
                        else:
                            self.logger.info("apt-get %s failed, maybe you should change sources and retry." % key)
                            self.apt_update_status = False
                            self.apt_update_signal.emit(key, 3)
                            self.exit(0)

        if not flag and self.apt_update_status:
            for key in self.install_list:
                if ADKUtils.is_apt_installed(key):
                    continue

                if self.stop_flag:
                    self.logger.info("apt thread paused. key = %s" % key)
                    return

                self.logger.info("apt-get install " + key + " begin.")

                self.apt_install_begin_signal.emit(key)

                if self.b_sudo:
                    command_str = 'echo ' + self.passwd + ' | sudo -S apt-get install ' + key + ' -y >> ' + self.apt_log_path
                    command_str_x = 'echo ' + '***' + ' | sudo -S apt-get install ' + key + ' -y >> ' + self.apt_log_path

                else:
                    command_str = 'apt-get install ' + key + ' -y >> ' + self.apt_log_path
                    command_str_x = 'apt-get install ' + key + ' -y >> ' + self.apt_log_path

                self.logger.info(command_str_x)

                (ret, output) = subprocess.getstatusoutput(command_str)

                if 0 == ret:
                    self.logger.info("apt-get install %s successfully." % key)

                    self.apt_install_signal.emit(key, True)
                else:
                    self.logger.info("apt-get install %s failed, maybe you should change sources and retry " % key)

                    self.apt_install_signal.emit(key, False)

                self.logger.info(time.asctime(time.localtime(time.time())))
            for key in self.install_list:
                if not ADKUtils.is_apt_installed(key):
                        self.apt_all_have_done.emit()
                        self.exit()
            self.apt_all_have_done.emit()

        if not self.apt_update_status:
            for key in self.install_list:
                if not ADKUtils.is_apt_installed(key):
                    self.apt_install_signal.emit(key, False)



class PIPInstallThread(QThread):

    # tell main which package begin to install.
    install_begin_signal = pyqtSignal(str)

    # tell main the pacakage install result.
    install_signal = pyqtSignal(str, bool)

    # tell main the package have been already installed.
    already_installed = pyqtSignal(str)

    # tell main all have been down.
    pip2_all_have_done = pyqtSignal()

    pip3_all_have_done = pyqtSignal()

    # insall_list in the install list will be install by apt
    def __init__(self, install_list, log_path, pip2=True, passwd=None, mylogger=None):
        """
        initial the apt install thread.
        :param install_list: the list will be installed by apt-get.
        :param atp_log_path: the path to save the apt-get install log. default: /tmp/makesd/apt_log/.*.log
        :param b_apt_need_update: if need to do apt-get update. default: False.
        """
        super(PIPInstallThread, self).__init__()
        self.install_list = install_list
        self.log_path = log_path
        self.pip2 = pip2
        self.passwd = passwd

        # if logger==None:
        #     self.logger = Log(self.log_path, __name__).getlog()
        # else:
        self.logger = mylogger

        self.stop_flag = False

    def run(self):

        # if pip have been installed.

        # while not ADKUtils.is_pip_self_installed(pip2=self.pip2, passwd=self.passwd):
        #
        #     if self.pip2:
        #         self.logger.info("[ERROR] command sudo pip2 --version return error, pip2 still not installed, please check, and you can install pip2 manual then retry.")
        #     else:
        #         self.logger.info("[ERROR] command sudo pip3 --version return error, pip3 still not installed, please check, and you can install pip3 manual then retry")
        #
        #     return

        for key in self.install_list:

            if self.stop_flag:
                self.logger.info("apt thread paused. pip2=%s, key=%s" %(self.pip2, key[0]))
                return

            # firstly check if the package have been already installed.
            if ADKUtils.is_pip_installed(key[0], self.pip2):
                self.logger.info(key[0] + " already installed. no need install again.")
                self.already_installed.emit(key[0])
                continue

            # then begin to install.
            self.logger.info("pip install " + key[0] + " begin.")
            self.install_begin_signal.emit(key[0])

            # (ret, output) = subprocess.getstatusoutput(
            #     key[1] + ' >> ' + ADKUtils.get_log_file(key[0], self.log_path))
            (ret, output) = subprocess.getstatusoutput(
                key[1] + ' >> ' + self.log_path)
            # self.apt_pkg_signal.emit(key)
            if 0 == ret:
                self.logger.info(key[1] + " successfully.")

                self.install_signal.emit(key[0], True)
            else:
                self.logger.info(key[1] + " failed, maybe you should change sources and retry")

                self.install_signal.emit(key[0], False)

        if self.pip2:
            self.pip2_all_have_done.emit()
        else:
            self.pip3_all_have_done.emit()

        self.exit(0)


class MakeSDThread(QThread):

    make_sd_begin_signal = pyqtSignal()
    make_sd_progress_signal = pyqtSignal(int)
    make_sd_progress_result = pyqtSignal(bool)
    make_sd_card_not_ok = pyqtSignal(bool)

    # (ret, output) = subprocess.getstatusoutput("python3 make_sd_card.py local " + self.sd_name)
    def __init__(self, working_path, sd_name, log_file, log_result, eth0_ip, usb_ip, sudo_passwd, mylogger):
        """
        initial the apt install thread.
        :param install_list: the list will be installed by apt-get.
        :param atp_log_path: the path to save the apt-get install log. default: /tmp/makesd/apt_log/.*.log
        :param b_apt_need_update: if need to do apt-get update. default: False.
        """
        super(MakeSDThread, self).__init__()
        self.sd_name = sd_name
        self.log_file = log_file
        self.working_path = working_path
        self.log_result = log_result
        self.eth0_ip = eth0_ip
        self.usb_ip = usb_ip
        self.sudo_passwd = sudo_passwd
        self.logger = mylogger

        #self.logger = Log(self.log_file, __name__).getlog()

    def run(self):

        # (ret, output) = subprocess.getstatusoutput("python3 make_sd_card.py local " + self.sd_name + " " + self.log_file)

        make_sd_card_proxy = MakeSDCardProxy(self.working_path, self.log_file, self.log_result, eth0_ip= self.eth0_ip, usb_ip=self.usb_ip, mylogger=self.logger)

        # ret = make_sd_card_proxy.check_sd(self.sd_name)
        #
        # if not ret:
        #     self.make_sd_card_not_ok.emit(False)
        #     self.logger.info("sd card not ok, please check.")
        #     self.exit(0)

        self.make_sd_begin_signal.emit()

        result = make_sd_card_proxy.process_local_installation(self.sd_name)

        if result:
            self.make_sd_progress_result.emit(True)
            self.logger.info("Make SD card successfully!")
        else:
            time.sleep(10)
            self.make_sd_progress_result.emit(False)
            self.logger.info("Make SD card failed, please check the log.")

        self.exit(0)


class MakeSDUIThread(QThread):

    make_sd_ui_end =  pyqtSignal()
    make_sd_sudo_passwd_wrong = pyqtSignal()

    # (ret, output) = subprocess.getstatusoutput("python3 make_sd_card.py local " + self.sd_name)
    def __init__(self, command_str):
        """
        initial the apt install thread.
        :param install_list: the list will be installed by apt-get.
        :param atp_log_path: the path to save the apt-get install log. default: /tmp/makesd/apt_log/.*.log
        :param b_apt_need_update: if need to do apt-get update. default: False.
        """
        super(MakeSDUIThread, self).__init__()
        self.command_str = command_str


    def run(self):
        (ret, output) = subprocess.getstatusoutput(self.command_str)
        print(ret, output)
        if ret != 0 and output.find("incorrect") > 1:
            self.make_sd_sudo_passwd_wrong.emit()

        self.make_sd_ui_end.emit()

        self.exit(0)


class MSInstallUIThread(QThread):

    ms_install_ui_end =  pyqtSignal()

    # (ret, output) = subprocess.getstatusoutput("python3 make_sd_card.py local " + self.sd_name)
    def __init__(self, command_str):
        super(MSInstallUIThread, self).__init__()
        self.command_str = command_str


    def run(self):
        subprocess.getstatusoutput(self.command_str)

        self.ms_install_ui_end.emit()

        self.exit(0)


class ExecuteCommandThread(QThread):
    execute_begin = pyqtSignal()
    execute_end = pyqtSignal(bool)

    def __init__(self, command_str):
        super(ExecuteCommandThread, self).__init__()
        self.command_str = command_str
        print(command_str)

    def run(self):
        self.execute_begin.emit()

        (ret, output) = subprocess.getstatusoutput(self.command_str)

        self.execute_end.emit(ret == 0)

        self.exit(0)


class ConnectThread(QThread):

    already_connect_signal = pyqtSignal(bool, str)
    customize_signal = pyqtSignal(bool, str)
    configure_signal = pyqtSignal(bool, str, str, str)

    def __init__(self, remote_ip, usb_card, passwd, project_path):
        super(ConnectThread, self).__init__()
        self.remote_ip = remote_ip
        self.usb_card = usb_card
        self.passwd = passwd
        self.project_path = project_path
        self.default_passwd = ADKUtils.read_default_passwd_func(self.project_path)

    def run(self):

        sudo_prefix = 'echo ' + self.passwd + " | sudo -S "
        subprocess.getstatusoutput(sudo_prefix + "ifdown " + self.usb_card)
        subprocess.getstatusoutput(sudo_prefix + 'ifup ' + self.usb_card)
        ret = subprocess.getstatusoutput(sudo_prefix + 'service NetworkManager restart')
        time.sleep(1)

        try:
            client = paramiko.SSHClient()
            client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            client.connect(self.remote_ip, 22, username="HwHiAiUser", password=self.default_passwd, timeout=1)
            self.already_connect_signal.emit(True, self.remote_ip)
            return

        except Exception as e:
            print("cannot ssh to your remote host, start configure......")
            base_ip = 123
            self_ip = self.remote_ip[:self.remote_ip.rindex(".")] + ".123"
            sudo_prefix = 'echo ' + self.passwd + " | sudo -S "
            (ret, output) = subprocess.getstatusoutput(
                self.project_path + '/configure_usb_ethernet.sh -s ' + self.usb_card + ' ' + self_ip)
            print(output)
            time.sleep(1)
            subprocess.getstatusoutput(sudo_prefix + 'ifdown ' + self.usb_card)
            subprocess.getstatusoutput(sudo_prefix + 'ifup ' + self.usb_card)
            subprocess.getstatusoutput(sudo_prefix + 'service NetworkManager restart')
            time.sleep(1)
            while ret == 4:
                base_ip += 1
                self_ip = self.remote_ip[:self.remote_ip.rindex(".")] + "." + str(base_ip)
                (ret, output) = subprocess.getstatusoutput(
                    './configure_usb_ethernet.sh -s ' + self.usb_card + ' ' + self_ip)

            if ret == 5:
                self.customize_signal.emit(True, output)
                return

            if ret == 0:
                self.configure_flag = True

        try:
            client = paramiko.SSHClient()
            client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            client.connect(self.remote_ip, 22, username="HwHiAiUser", password=self.default_passwd, timeout=1)
            if not self.configure_flag:
                self.already_connect_signal.emit(True, self.remote_ip)
            else:
                self.configure_signal.emit(True, self.usb_card, self_ip, self.remote_ip)
            return

        except Exception as e:
            self.customize_signal.emit(True, "ssh failed")
            return


class ReadLogThread(QThread):

    update_log_signal = pyqtSignal(str)

    def __init__(self, log_file):
        super(ReadLogThread, self).__init__()
        self.log_file = log_file

    def run(self):
        # print("running read_log threading：")
        # firstly clear the log


        pos = 0
        while True:
            time.sleep(0.2)
            if not os.path.exists(self.log_file):
                time.sleep(1)
                continue

            con = open(self.log_file)
            if pos != 0:
                con.seek(pos, 0)
            while True:
                line = con.readline()
                if line.strip():
                    # print(line.strip())

                    self.update_log_signal.emit(line.strip())
                pos = pos + len(line)
                if not line.strip():
                    break
            con.close()


class ADKUtils(object):
    def __init__(self):
        pass

    @classmethod
    def is_file_path_exists(cls, file_path):
        # todo: if it is ok? according the path and size to judge if it is existed.
        if not os.path.exists(file_path):
            return False
        return True

    @classmethod
    def is_file_size_ok(cls, file_path, file_size):
        equal = 1
        big = 2
        small = 3
        if file_size == os.path.getsize(file_path):
            return equal
        elif file_size > os.path.getsize(file_path):
            return small
        else:
            return big

    @classmethod
    def get_log_file(cls, key, apt_log_path):
        return apt_log_path + "/." + key + ".log "

    @classmethod
    def is_apt_installed(cls, key):
        # (ret, output) = subprocess.getstatusoutput("dpkg -l " + key)
        (ret, output) = subprocess.getstatusoutput("dpkg --get-selections | grep -v deinstall | awk -F' ' '{print $1}' | grep -Fx " + key)
        if output == key:
            return True
        (ret, output) = subprocess.getstatusoutput("dpkg --get-selections | grep -v deinstall |  awk -F' ' '{print $1}' | grep -w " + key + " | grep " + key + ":")
        if output:
            return True
        return False

    @classmethod
    def is_pip_installed(cls, key, pip2=True):
        # todo maybe the result is not correct.
        if pip2:
            (ret, output) = subprocess.getstatusoutput("pip2 list | grep -w " + key + " | wc -l")
        else:
            (ret, output) = subprocess.getstatusoutput("pip3 list | grep -w " + key + " | wc -l")

        result = output.split("\n")[-1]

        return int(result) > 0

    @classmethod
    def is_pip_self_installed(cls, pip2=True, passwd=None):
        if pip2:
            (ret, output) = subprocess.getstatusoutput('echo ' + passwd + "| sudo -S pip2 --version")
        else:
            (ret, output) = subprocess.getstatusoutput('echo ' + passwd + "| sudo -S pip3 --version")
        return ret == 0

    @classmethod
    def read_default_passwd_func(cls, project_path):
        with open(project_path + '/default_passwd.pickle', 'rb') as file:
            read_passwd = pickle.load(file)
        passwd = base64.b64decode(read_passwd)
        origin_passwd = passwd.decode("utf-8")
        return origin_passwd

    @classmethod
    def disable_item_comboBox(cls, cBox, List, v=0):
        """
        将下拉按钮中的某些项目批量禁用
        :param cBox: comboBox对象
        :param List: 需要禁用的项目,列表数据,如[1,2,5,6]
        :param v: 0为禁用,1|32为解除
        """
        for i in range(len(List)):
            index = cBox.model().index(List[i], 0)  # 选择需要设定的项目
            # print(List[i])
            cBox.model().setData(index, v, Qt.UserRole - 1)  # 禁用comboBox的指定项目

    @classmethod
    def show_message(cls, msg):
        dialog_result = QDialog()
        result_ui = DialogResult.Ui_Dialog()
        result_ui.setupUi(dialog_result)
        result_ui.label.setText(msg)

        return dialog_result.exec() == QDialog.Accepted

    @classmethod
    def show_message_if_to_delete(cls, msg):

        dialog_result = QDialog()
        result_ui = DialogResult.Ui_Dialog()
        result_ui.setupUi(dialog_result)
        result_ui.label.setText(msg)
        result_ui.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok)

        return dialog_result.exec() == QDialog.Accepted

    @classmethod
    def read_decode_func(cls, dir_name):
        with open(dir_name + '/passwd_manager.pickle', 'rb') as file:
            read_passwd = pickle.load(file)
        passwd = base64.b64decode(read_passwd)
        origin_passwd = passwd.decode("utf-8")
        return origin_passwd

    @classmethod
    def md5sum_func(cls, file_path):
        (ret, output) = subprocess.getstatusoutput('md5sum ' + file_path + " | awk -F ' ' '{print $1}'")
        time.sleep(1)
        return output



